// void, Obj This, point pt

Hero this;
Obj o, u;
point dpt;
bool bSquadTarget;
//bool bAnimalTarget;
int x, rcount, i;

this = This.AsHero();
Sleep(30);
if(!.IsValid) return;

//pr("hero advance");
if(IsAIPlayer(.player)){
	.FormSetupAndMoveTo (pt, 0, 0, true);
	// Wait for army to exit
	while(!.IsArmyOutside())
		.FormKeepMoving(500);
	while(.HasPath())
	{
		//.pr("Hero::Advance:Looking for enemys");
		if (.IsEnemyInSquadSight()) {
			bSquadTarget = false;
			u = .BestTargetInSquadSight();
			if (u.IsAlive()) if (u.attack > 0)
				bSquadTarget = true;
			for (i = 0; !bSquadTarget && i < .army.count; i += 1) {
				u = .army[i].AsUnit.BestTargetInSquadSight();
				if (u.IsAlive()) if (u.attack > 0)
					bSquadTarget = true;
			}		
			if (bSquadTarget) {
				Sleep(rand(200)+300);
				.AddCommand(true, "advance", pt);
				.AddCommand(true, "engage");
				return;
			}
		}
		//.pr("hero::advance: No Enemy");
		//.pr("hero::advance:moving");
		.FormKeepMoving (1500);
	}	

	dpt = .GetFinalPartyOrientation() - Point(1024, 1024);
	if (dpt.x != 0 || dpt.y != 0)
		.Face(.pos + dpt);
	
} else {
	Unit ua;

if(.HasItem("irage_battle") 
|| .HasItem("iretreat_notai")){
	bSquadTarget = false;
		
	o = .BestTargetInSquadSight();
	if(.IsValidTarget(o)) 

	if(o.IsAlive()) 
		if(.IsValidTarget(o))
		if(o.IsVisible)
		if(.DistTo(o.pos) > .min_range)
			if(.DistTo(o.pos) < 300)
				if(o.IsMilitary || o.IsHeirOf("Catapult"))
					bSquadTarget = true;
	
	for(x=0; !bSquadTarget && x<.army.count; x+=1){
		
		ua = .army[x].AsUnit;
		if(ua.IsValid){
			
			o = ua.BestTargetInSquadSight();
			
			if(o.IsAlive()) 
				if(.IsValidTarget(o))
				if(o.IsVisible)
				if(.DistTo(o.pos) > .min_range)
					if(ua.DistTo(o.pos) < 200)
						if(o.IsMilitary || o.IsHeirOf("Catapult"))
							bSquadTarget = true;
		}
	}
	if(o.IsAlive())
	if(o.AsUnit.hero.IsValid)
		if(o.AsUnit.hero.command == "retreat_notai" || 
			o.AsUnit.hero.command == "retreat_bld_notai")
			bSquadTarget = false;
			
	if(bSquadTarget){
		Sleep(rand(200)+300);
		.AddCommand(true, "advance", pt);
		.AddCommand(true, "engage");
		return;
	}
		
} else {

	.FormSetupAndMoveTo (pt, 0, 0, true);
	
	while(!.IsArmyOutside())
		.FormKeepMoving(800);
		
	rcount = 0;
	for(x=0; x<.army.count; x+=1){
		
		ua = .army[x].AsUnit;
		if(ua.IsValid){
			if(ua.IsRanged)
				rcount+=1;
		}
	}
	if(rcount > 0) rcount = 8*rcount;
	while(.HasPath()){
		
		if(.IsEnemyInSquadSight()){	                
			//pr("advance: is enemy");		
			bSquadTarget = false;
			
			o = .BestTargetInSquadSight();
			if(.IsValidTarget(o)) 
				if(o.IsAlive()) 
					if(.IsValidTarget(o))
					if(o.IsVisible)
					if(.DistTo(o.pos) > .min_range)
						if(.DistTo(o.pos) < (300+rcount))
							if(o.IsMilitary || o.IsHeirOf("Catapult"))
								bSquadTarget = true;
				
			for(x=0; !bSquadTarget && x<.army.count; x+=1){
				
				ua = .army[x].AsUnit;
				if(ua.IsValid){
					
					o = ua.BestTargetInSquadSight();
					
					if(o.IsAlive())
						if(.IsValidTarget(o)) 
						if(o.IsVisible)
						if(.DistTo(o.pos) > .min_range)
							if(ua.DistTo(o.pos) < (250+rcount))
								if(o.IsMilitary || o.IsHeirOf("Catapult"))
									bSquadTarget = true;
				}
			}
			if(o.IsAlive())
			if(o.AsUnit.hero.IsValid)
				if(o.AsUnit.hero.command == "retreat_notai" ||
					o.AsUnit.hero.command == "retreat_bld_notai")
					bSquadTarget = false;
			
			if(bSquadTarget){
				Sleep(rand(200)+300);
				.AddCommand(true, "advance", pt);
				.AddCommand(true, "engage");
				return;
			}
			.FormKeepMoving (500);
		} else .FormKeepMoving (1500);
	}	

	dpt = .GetFinalPartyOrientation() - Point(1024, 1024);

	if(dpt.x!=0 || dpt.y!=0)
		.Face(.pos+dpt);
}
}
